package uk.co.q3c.deplan.client.domain.resource;

import java.util.Date;
import java.util.List;

import uk.co.q3c.deplan.client.domain.DomainObject;
import uk.co.q3c.deplan.client.domain.StructureChangeNotifier;
import uk.co.q3c.deplan.client.domain.task.BaseTask;
import uk.co.q3c.deplan.client.domain.task.BaseTask;
import uk.co.q3c.deplan.client.domain.task.StartFinishTimes;

import com.googlecode.objectify.Key;

/**
 * 
 * @author DSowerby 7 May 2008 00:13:43
 * @see AbstractResource
 * @see IndividualResource
 * @see ResourceGroup
 */
public interface Resource extends StructureChangeNotifier, DomainObject {

	public abstract int effortAvailable(Date di, double units);

	/**
	 * {@link IndividualResource#bookEffort} {@link ResourceGroup#bookEffort}
	 * 
	 * @param effortWanted
	 * @param di
	 * @return
	 * @throws PersistenceReferenceException
	 */
	public abstract StartFinishTimes bookEffort(int effortWanted, Date date, BaseTask task) throws PersistenceReferenceException;

	public String getName();

	public void setName(String name);

	/**
	 * returns the number of minutes booked on the specified day, 0 if the date is out of range
	 * 
	 * @param cal
	 * @return
	 */
	public int timeBooked(Date date);

	public abstract void addAdjustment(Date date, boolean absolute, int minutes);

	// public abstract void addTask(BaseTask task);
	//
	// public abstract void removeTask(BaseTask task);

	/**
	 * Returns a the map of resources contained within this resource.
	 * 
	 * @return
	 */
	public abstract List<IndividualResource> getResources();

	/**
	 * true if this is a group of resources
	 * 
	 * @return
	 */
	public abstract boolean isGroup();

	public abstract List<? extends IndividualResource> resources();

	public abstract List<IndividualResource> getIndividualResources(List<IndividualResource> list);

	/**
	 * returns the number of individual resources associated with this resource. For {@link IndividualResource} this will always be 1; for a
	 * {@link ResourceGroup} it will be the number of contained resources. Note that to be absolutely sure resource is assigned you will
	 * also need to check {@link BaseTask#getAssignedUnits() to ensure that an assignment of effort has been made.}
	 * 
	 * @return
	 */
	public abstract int count();

	// public ResourceGroup getParent();

	/**
	 * Returns true if this resource uses <code>usedResource</code>. If the implementor is an individual resource, it should return true if
	 * this==usedResource
	 * 
	 * @param usedResource
	 * @return
	 */
	public abstract boolean uses(IndividualResource usedResource);

	Key<? extends Resource> getKey() throws PersistenceReferenceException;

}